package com.cnebula.uas.sso.controller;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.servlet4preview.http.HttpServletRequest;
import org.apache.http.client.utils.URIBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.cnebula.uas.sso.ConfAdmin;
import com.cnebula.uas.sso.idp.DelegateIDP;
import com.cnebula.uas.sso.idp.DelegateIDPFactory;
import com.cnebula.uas.sso.model.IdpCredential;
import com.cnebula.uas.sso.model.OKUser;
import com.cnebula.uas.sso.model.UMPrincipal;
import com.cnebula.uas.sso.service.IDPAuthService;
import com.cnebula.uas.sso.service.UMPrincipalService;
import com.fasterxml.jackson.databind.ObjectMapper;

@Controller
@RequestMapping(value = "/uas/sso/next")
public class SSONextController {

	@Autowired
	IDPAuthService authService;

	ObjectMapper mapper = new ObjectMapper();

	Logger log = LoggerFactory.getLogger(SSONextController.class);

	@Autowired
	ConfAdmin conf;

	@Autowired
	UMPrincipalService umPrincipalService;

	/**
	 * 请求登录
	 * 
	 * @throws URISyntaxException
	 * @throws IOException
	 */
	@RequestMapping(value = "/auth", method = RequestMethod.POST)
	public void login(IdpCredential idpCredential, HttpServletResponse response)
			throws URISyntaxException, IOException {

		// 验证用户名和密码
		String artifact = null;
		try {
			ResponseEntity<String> rst = authService.loginLSP(idpCredential.getLoginId(), idpCredential.getPassword(),
					idpCredential.getIdpCode());
			if (rst.getStatusCodeValue() != 200) {
				response.sendError(rst.getStatusCodeValue(), rst.getBody());
				return;
			}
			artifact = rst.getBody();
		} catch (Exception e) {
			response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
			return;
		}

		// 携带 goto idp artifact 重定向到 sp
		URIBuilder builder = new URIBuilder(idpCredential.getSp());
		builder.addParameter("idp", idpCredential.getIdpCode());
		builder.addParameter("artifact", artifact);
		builder.addParameter("goto", idpCredential.getGotoURL());

		response.sendRedirect(builder.build().toString());
	}

	/**
	 * 跳转到LSP登录页面
	 * 
	 * @throws URISyntaxException
	 * @throws IOException
	 */
	@RequestMapping(value = "/idp/{idpCode}")
	@GetMapping
	public String idp(@PathVariable String idpCode, @RequestParam String sp,
			@RequestParam(value = "goto") String gotoURL, HttpServletRequest request, HttpServletResponse response,
			ModelMap map) throws URISyntaxException, IOException {

		// TODO 核实 idp是本地认证还是 第三方的认证

		DelegateIDP delegateIDP = null;
		if (idpCode.equals("510500")) {
			// 深圳大学 idp
			delegateIDP = DelegateIDPFactory.getDelegateIDP("delegateIDP510500");
		}

		if (delegateIDP != null) {
			return "redirect:" + delegateIDP.idp(sp, gotoURL);
		}

		map.addAttribute("sp", sp);
		map.addAttribute("idpCode", idpCode);
		map.addAttribute("gotoURL", gotoURL);

		return "signin";

	}

	/**
	 * idp认证成功后的回调地址
	 * 
	 * @param idpCode
	 * @param sp
	 * @param gotoURL
	 * @param okapiToken
	 * @param response
	 * @throws URISyntaxException
	 * @throws IOException
	 */
	@RequestMapping(value = "/idp/{idpCode}/callback")
	@GetMapping
	public void delegateIdpCallback(@PathVariable String idpCode, @RequestParam Map<String, String> params,
			HttpServletResponse response) throws URISyntaxException, IOException {

		// check parameter
		String sp = params.get("sp");
		String gotoURL = params.get("goto");

		if (sp == null || sp.isEmpty()) {
			response.sendError(HttpServletResponse.SC_BAD_REQUEST, "not criterion request, missing sp parameter");
			return;
		}

		if (gotoURL == null || gotoURL.isEmpty()) {
			response.sendError(HttpServletResponse.SC_BAD_REQUEST, "not criterion request, missing goto parameter");
			return;
		}

		DelegateIDP delegateIDP = null;
		if (idpCode.equals("510500")) {
			// 深圳大学 idp
			delegateIDP = DelegateIDPFactory.getDelegateIDP("delegateIDP510500");
		}

		if (delegateIDP != null) {
			response.sendRedirect(delegateIDP.callback(sp, idpCode, gotoURL, params));
		} else {
			response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
					"not found " + idpCode + " idp delegate implements");
		}
	}

	/**
	 * 验证artifact
	 * 
	 * @return
	 */
	@RequestMapping(value = "/valid")
	@GetMapping
	public ResponseEntity<String> valid(String artifact) {
		String content = null;
		try {
			ResponseEntity<String> rst = authService.checkArtifact(artifact, null);
			content = rst.getBody();
			if (rst.getStatusCodeValue() != 200) {
				return ResponseEntity.ok(content);
			}

			OKUser okUser = mapper.readValue(content, OKUser.class);

			UMPrincipal um = umPrincipalService.okUserToUM(okUser);
			content = umPrincipalService.exportXML(um);

			log.debug("[res] " + content);

		} catch (Exception e) {
			log.warn(e.getMessage());
			return ResponseEntity.status(500).body(e.getMessage());
		}

		return ResponseEntity.ok(content);
	}

	public static void main(String[] args) throws URISyntaxException {
		URIBuilder builder = new URIBuilder(
				"http://uas.tj.calis.edu.cn:8090/amconsole/AuthServices/134800?verb=splogin");
		// builder.setParameter("sp",
		// "http://uas.tj.calis.edu.cn:8090/amconsole/AuthServices/134800?verb=splogin");
		builder.setParameter("goto",
				"http://cuas.calis.edu.cn:8090/amconsole/AuthServices?verb=splogin&goto=http%3A%2F%2Fwww.calis.edu.cn%2Feduchina%2Fpages%2Fgoto.jsp&idp=134800");
		builder.setParameter("idp", "134800");

		System.out.println(builder.build().toString());
	}
}
